package com.ndood.admin.service.system.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.ndood.admin.pojo.comm.dto.DataTableDto;
import com.ndood.admin.pojo.system.DictPo;
import com.ndood.admin.pojo.system.dto.DictDto;
import com.ndood.admin.pojo.system.query.DictQuery;
import com.ndood.admin.repository.system.DictRepository;
import com.ndood.admin.repository.system.DictValueRepository;
import com.ndood.admin.service.system.SystemDictService;
import com.ndood.core.utils.JPAUtil;

/**
 * 字典模块业务类
 * @author ndood
 */
@Service
public class SystemDictServiceImpl implements SystemDictService {

	@Autowired
	private DictRepository dictDao;
	
	@Autowired
	private DictValueRepository dictValueDao;
	
	@Override
	public void addDict(DictDto dto) throws Exception {
		// Step1: 补充相关默认字段
		dto.setCreateTime(new Date());
		dto.setUpdateTime(new Date());
		
		// Step2: 保存字典
		DictPo po = new DictPo();
		JPAUtil.childToFather(dto, po);
		po.setValues(dto.getValues());
		dictDao.save(po);
	}

	@Override
	public void batchDeleteDict(Integer[] ids) {
		// dictDao.deleteByIds(Arrays.asList(ids));
		for (Integer id : ids) {
			dictDao.deleteById(id);
		}
	}

	@Override
	public void updateDict(DictDto dto) throws Exception {
		// Step1: 删除旧字典值
		DictPo po = dictDao.findById(dto.getId()).get();
		dictValueDao.deleteInBatch(po.getValues());
		
		// Step2: 保存新的值
		JPAUtil.childToFather(dto, po);
		po.setValues(dto.getValues());
		dictDao.save(po);
	}
	
	@Override
	public DictDto getDict(Integer id) throws Exception {
		DictPo po = dictDao.findById(id).get();
		
		DictDto dto = new DictDto();
		JPAUtil.fatherToChild(po, dto);
		dto.setValues(po.getValues());
		return dto;
	}

	@Override
	public DataTableDto pageDictList(DictQuery query) throws Exception {
		// Step1: 封装查询参数
		String keywords = query.getKeywords();
		Date startTime = query.getStartTime();
		Date endTime = query.getEndTime();
		String code = query.getCode();
		String desc = query.getDesc();
		Integer status = query.getStatus();
		
		Integer pageSize = query.getLimit();
		Integer pageNo = query.getPageNo();
		
		List<Sort.Order> orders = new ArrayList<Sort.Order>();
		Sort.Order order = new Sort.Order(Sort.Direction.ASC, "sort");
		orders.add(order);
		Pageable pageable = new PageRequest(pageNo, pageSize, new Sort(orders));

		// Step2: 进行复杂查询
		Page<DictPo> page = dictDao.findAll(new Specification<DictPo>() {
			@Override
			public Predicate toPredicate(Root<DictPo> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
				List<Predicate> ps = new ArrayList<>();
				if (!StringUtils.isEmpty(keywords)) {
					Predicate p1 = cb.like(root.get("code"), "%" + keywords + "%");
					Predicate p2 = cb.like(root.get("desc"), "%" + keywords + "%");
					ps.add(cb.or(p1,p2));
				}
				if(status!=null){
					ps.add(cb.equal(root.get("status"), status));
				}
				if(startTime!=null){
					ps.add(cb.greaterThanOrEqualTo(root.get("createTime"), startTime));
				}
				if(endTime!=null){
					ps.add(cb.lessThan(root.get("createTime"), endTime));
				}
				if(!StringUtils.isEmpty(code)){
					ps.add(cb.equal(root.get("code"), code));
				}
				if(!StringUtils.isEmpty(desc)){
					ps.add(cb.like(root.get("desc"), "%" + desc + "%"));
				}
				return cb.and(ps.toArray(new Predicate[ps.size()]));
			}
		}, pageable);
		
		// Step3: 转换成dto
		List<DictDto> list = new ArrayList<DictDto>();
		for (DictPo po : page.getContent()) {
			DictDto dto = new DictDto();
			JPAUtil.fatherToChild(po, dto);
			dto.setValues(po.getValues());
			list.add(dto);
		}
		return new DataTableDto(list, page.getTotalElements());
	}
}
